<?php
namespace Lib;

final class Ext {

	/**
	 * 根据指定的参数组装并返回一个 PATHINFO，为便于控制器名和操作名在URL中被清晰的描述，控制器名和操作名均被转为小写，且所有非首字母在从大写转至小写后，还前缀一个 _ 字符
	 *
	 * - 控制器名示例：Admin\User
	 * - 操作名示例：Login
	 * - 变量列表示例：Array('username'=>'Username', 'password'=>'Password')
	 *
	 * @param string $controller 控制器名
	 * @param string $action 操作名
	 * @param array|object $parameter 变量列表，键名为变量名，元素值即变量值
	 * @return string
	 */
	static public function url($controller, $action, $parameter = array()) {
		$controller = strtolower(str_replace(str_split(HHO::$config['tick'] . '\\'), '~', preg_replace('/([a-z])([A-Z])/', '$1_$2', $controller)));
		
		$action = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $action));
		
		$url = array('/' . $controller);
		
		$url[] = &$action;
		
		foreach ($parameter as $name => $value) {
			$url[] = $name;
			$url[] = $value;
		}
		
		return implode(HHO::$config['tick'][0], $url);
	}

	/**
	 * 将下划线命名法形式的控制器名或操作名转为帕斯卡（Pascal）命名法形式，转换规则与 Core\HHO::pascal() 相同
	 *
	 * - 参数 $name 值示例：admin~user_member
	 *
	 * @param string $name
	 * @return string
	 */
	static public function pascal($name) {
		$name = str_replace(str_split(HHO::$config['tick']), '~', $name);
		
		return str_replace(array(' ', "\t"), array('\\', ''), ucwords(str_replace(array('~', '_'), array(' ', "\t"), $name)));
	}

	/**
	 * 获得客户端IP地址
	 *
	 * @return string
	 */
	static public function getip() {
		// 使用透明代理服务器
		if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]) && preg_match_all('/(\d{1,3}\.){3}\d{1,3}/s', $_SERVER['HTTP_X_FORWARDED_FOR'], $tmp)) {
			foreach ($tmp[0] as $ip) {
				$long = bindec(decbin(ip2long($ip)));
				
				// 192.168.0.0 - 192.168.255.255、172.16.0.0 - 172.31.255.255、10.0.0.0 - 10.255.255.255
				if ($long >= 3232235520 && $long <= 3232301055 || $long >= 2886729728 && $long <= 2887778303 || $long >= 167772160 && $long <= 184549375) {
					continue;
				}
				
				return $ip;
			}
			
			return '0.0.0.0';
		}
		
		if (isset($_SERVER['HTTP_CLIENT_IP']) && $_SERVER['HTTP_CLIENT_IP']) {
			return $_SERVER['HTTP_CLIENT_IP'];
		}
		
		if (isset($_SERVER["HTTP_X_REAL_IP"]) && preg_match_all('/(\d{1,3}\.){3}\d{1,3}/s', $_SERVER['HTTP_X_REAL_IP'], $tmp)) {
			foreach ($tmp[0] as $ip) {
				$long = bindec(decbin(ip2long($ip)));
				
				// 192.168.0.0 - 192.168.255.255、172.16.0.0 - 172.31.255.255、10.0.0.0 - 10.255.255.255
				if ($long >= 3232235520 && $long <= 3232301055 || $long >= 2886729728 && $long <= 2887778303 || $long >= 167772160 && $long <= 184549375) {
					continue;
				}
				
				return $ip;
			}
			
			return '0.0.0.0';
		}
		
		if (isset($_SERVER["HTTP_FROM"]) && preg_match('/(?:\d{1,3}\.){3}\d{1,3}/', $_SERVER["HTTP_FROM"])) {
			return $_SERVER["HTTP_FROM"];
		}
		
		// 没有使用代理服务器
		if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR']) {
			return $_SERVER['REMOTE_ADDR'];
		}
		
		return '0.0.0.0';
	}

	/**
	 * 获得当前或指定时间当日 00:00:00 的 UNIX 时间戳
	 *
	 * @param int $timestamp
	 * @return int
	 */
	static public function datestamp($timestamp = NULL) {
		return $timestamp ? strtotime(date('Y-m-d 00:00:00', $timestamp)) : mktime(0, 0, 0);
	}

	/**
	 * 获得指定整数包含的仅限值列表。
	 *
	 * @param int $mode
	 * @return array
	 */
	function purview($mode) {
		$l = [];
		
		for ($i = 1; TRUE; $i += $i) {
			if ($i > $mode) {
				return $l;
			}
			
			$mode & $i && $l[] = $i;
		}
	}
}